<script lang="ts" setup name="QuickForm">
import { defineExpose, toRefs, defineEmits, ref, reactive, watch } from "vue";
import { Plus } from "@element-plus/icons-vue";
import { FormInstance, TabsPaneContext } from "element-plus";
// import { formProps, formEmits } from "./index";
import { IFormItem } from "./index";
import elementPlusIcons from "./elementPlusIcons";
import { QuickSvgIcon } from "@ainiteam/quick-vue3-ui";

const props = defineProps({
  model: {
    type: Object,
    default: () => {
      return {};
    },
  },
  items: {
    type: Array<IFormItem>,
    default: () => {
      return [];
    },
  },
  inline: {
    type: Boolean,
    default: false,
  },
  type: {
    type: String,
    default: "form",
  },
  actionSlot: {
    type: Boolean,
    default: false,
  },
  hiddenAction: {
    type: Boolean,
    default: false,
  },
  isDesign: {
    type: Boolean,
    default: false,
  },
  size: {
    type: String,
    default: "default",
  },
  labelPosition: {
    type: String,
    default: "left",
  },
  selectItem: {
    type: Object,
    default: () => { },
  },
});
const { model, inline, items, type, actionSlot, hiddenAction, isDesign, size,
  labelPosition,
  selectItem } = toRefs(props);
const emits = defineEmits(["onSubmit", "onSelect","onChange"]);

const currentFormItem = reactive<IFormItem>({});
const formRef = ref<FormInstance>();
const iconVisible = ref(false);
/**
 * tabs
 */
const activeName = ref("element");
const handleClick = (tab: TabsPaneContext, event: Event) => {
  console.log(tab, event);
};
const selectIcon = (item: any, option: any) => {
  item.select(option.value);
  iconVisible.value = false;
};
const iconClick = () => {
  iconVisible.value = true;
};
/**
 * 函数
 */
const submitForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  formEl.validate((valid, fields) => {
    if (valid) {
      console.log("submit!");
      emits("onSubmit", formRef.value);
    } else {
      console.log("error submit!", fields);
    }
  });
};
const resetForm = (formEl: FormInstance | undefined) => {
  if (!formEl) return;
  formEl.resetFields();
};
const handleSubmit = () => {
  submitForm(formRef.value);
};
const handleClear = () => {
  resetForm(formRef.value);
};
const handleFormItemClick = (item: IFormItem) => {
  emits("onSelect", item);
};
const getClassName = (item: IFormItem) => {
  let className = "";
  if (isDesign.value) {
    className = "form-design-item";
    if (item.id === (currentFormItem && currentFormItem.id)) {
      className = "form-design-item active";
    }
  }
  return className;
};
watch(
  () => model.value,
  (val) => {
    emits("onChange", val);
  },
  {
    // immediate:true,
    deep: true,
  }
);
watch(() => selectItem.value, (val) => {
  for (const key in val) {
    if (Object.prototype.hasOwnProperty.call(val, key)) {
      const element = val[key];
      currentFormItem[key] = element;
    }
  }
}, {
  deep: true
})
defineExpose({ handleSubmit, handleClear });
</script>
<template>
  <el-form ref="formRef" :model="model" :inline="inline" :size="size" :label-position="labelPosition">
    <template v-for="(item, index) in items" :key="index">
      <div :class="getClassName(item)" @click="handleFormItemClick(item)">
        <el-form-item v-if="
          type === 'search' ||
          (type === 'add' && !item.addHidden) ||
          (type === 'edit' && !item.editHidden) ||
          (type === 'detail' && !item.detailHidden) ||
          type === 'form'
        " :label="item.label" :label-width="item.labelWidth" :prop="type === 'detail' ? undefined : item.prop"
          :rules="type === 'detail' ? undefined : item.rules">
          <template v-if="item.type === 'radio'">
            <el-radio-group v-model="model[item.vModel]" :style="{ width: inline ? '400px' : '100%' }" :disabled="(type === 'add' && item.addDisabled) ||
              (type === 'edit' && item.editDisabled) ||
              type === 'detail'
              ">
              <el-radio v-for="(option, optionsIndex) in item.options" :key="optionsIndex" :value="option.value"
                size="large">{{ option.label }}</el-radio>
            </el-radio-group>
          </template>
          <template v-else-if="item.type === 'checkbox'">
            <el-checkbox-group v-model="model[item.vModel]" :style="{ width: inline ? '400px' : '100%' }" :disabled="(type === 'add' && item.addDisabled) ||
              (type === 'edit' && item.editDisabled) ||
              type === 'detail'
              ">
              <el-checkbox v-for="(option, optionsIndex) in item.options" :key="optionsIndex" :label="option.label"
                :value="option.value" />
            </el-checkbox-group>
          </template>
          <template v-else-if="item.type === 'select'">
            <el-select v-model="model[item.vModel]" :placeholder="item.placeholder" :multiple="item.multiple"
              :style="{ width: inline ? '400px' : '100%' }" :disabled="(type === 'add' && item.addDisabled) ||
                (type === 'edit' && item.editDisabled) ||
                type === 'detail'
                ">
              <el-option v-for="(option, optionsIndex) in item.options" :key="optionsIndex" :label="option.label"
                :value="option.value" />
            </el-select>
          </template>
          <template v-else-if="item.type === 'cascader'">
            <el-cascader v-model="model[item.vModel]" :options="item.treeOptions" :placeholder="item.placeholder"
              :props="{
                expandTrigger: 'hover',
              }" :style="{ width: inline ? '400px' : '100%' }" @change="item.change" />
          </template>
          <template v-else-if="item.type === 'textarea'">
            <el-input v-model="model[item.vModel]" :autosize="{ minRows: 5, maxRows: 10 }" type="textarea"
              :autocomplete="item.autocomplete" :placeholder="item.placeholder" :clearable="item.clearable"
              :style="{ width: inline ? '400px' : '100%' }" :readonly="(type === 'add' && item.addReadonly) ||
                (type === 'edit' && item.editReadonly) ||
                type === 'detail'
                " />
          </template>
          <template v-else-if="item.type === 'password'">
            <el-input v-model="model[item.vModel]" :autocomplete="item.autocomplete" :placeholder="item.placeholder"
              :clearable="item.clearable" type="password" show-password :style="{ width: inline ? '400px' : '100%' }"
              :readonly="(type === 'add' && item.addReadonly) ||
                (type === 'edit' && item.editReadonly) ||
                type === 'detail'
                " />
          </template>
          <template v-else-if="item.type === 'avatar'">
            <el-upload class="avatar-uploader" :action="item.actionUrl" :show-file-list="false" :headers="item.headers"
              :on-success="item.success" :before-upload="item.beforeUpload"
              :style="{ width: inline ? '400px' : '100%' }">
              <img v-if="model[item.vModel]" :src="model[item.vModel]" class="avatar" />
              <el-icon v-else class="avatar-uploader-icon">
                <Plus />
              </el-icon>
            </el-upload>
          </template>
          <template v-else-if="item.type === 'number'">
            <el-input v-model.number="model[item.vModel]" type="number" :autocomplete="item.autocomplete"
              :placeholder="item.placeholder" :clearable="item.clearable" :style="{ width: inline ? '400px' : '100%' }"
              :readonly="(type === 'add' && item.addReadonly) ||
                (type === 'edit' && item.editReadonly) ||
                type === 'detail'
                " />
          </template>
          <template v-else-if="item.type === 'switch'">
            <el-switch v-model="model[item.vModel]" :active-value="1" :inactive-value="0" />
          </template>
          <template v-else-if="item.type === 'date'">
            <el-date-picker v-model="model[item.vModel]" type="date" value-format="X" format="YYYY-MM-DD HH:mm:ss"
              :placeholder="item.placeholder" />
          </template>
          <template v-else-if="item.type === 'daterange'">
            <el-date-picker v-model="model[item.vModel]" type="daterange" range-separator="-" value-format="X"
              format="YYYY-MM-DD HH:mm:ss" :start-placeholder="item.placeholders ? item.placeholders[0] : '请选择开始日期'
                " :end-placeholder="item.placeholders ? item.placeholders[1] : '请选择结束日期'
                " />
          </template>
          <template v-else-if="item.type === 'datetime'">
            <el-date-picker v-model="model[item.vModel]" type="datetime" value-format="X" format="YYYY-MM-DD HH:mm:ss"
              :placeholder="item.placeholder" />
          </template>
          <template v-else-if="item.type === 'datetimerange'">
            <el-date-picker v-model="model[item.vModel]" type="datetimerange" range-separator="-" value-format="X"
              format="YYYY-MM-DD HH:mm:ss" :start-placeholder="item.placeholders ? item.placeholders[0] : '请选择开始日期'
                " :end-placeholder="item.placeholders ? item.placeholders[1] : '请选择结束日期'
                " />
          </template>
          <template v-else-if="item.type === 'tree'">
            <el-tree-select v-model="model[item.vModel]" :data="item.options" :check-strictly="true"
              :render-after-expand="false" :placeholder="item.placeholder" :style="{ width: inline ? '400px' : '100%' }"
              :disabled="(type === 'add' && item.addDisabled) ||
                (type === 'edit' && item.editDisabled) ||
                type === 'detail'
                " />
          </template>
          <template v-else-if="item.type == 'icon'">
            <el-popover placement="bottom" width="1000px" trigger="click">
              <template #reference>
                <el-input v-model="model[item.vModel]" :autocomplete="item.autocomplete" :placeholder="item.placeholder"
                  :clearable="item.clearable" :style="{
                    width: inline ? '400px' : '100%',
                  }" :readonly="(type === 'add' && item.addReadonly) ||
                    (type === 'edit' && item.editReadonly) ||
                    type === 'detail'
                    " @click="iconClick()">
                  <template #append>
                    <el-icon>
                      <component :is="model[item.vModel]" />
                    </el-icon>
                  </template>
                </el-input>
              </template>
              <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick">
                <el-tab-pane label="element官方icon" name="element">
                  <ul class="icon-list">
                    <li v-for="(option, index) in elementPlusIcons" :key="index" class="icon-item"
                      @click="selectIcon(item, option)">
                      <span class="svg-icon">
                        <el-icon style="font-size: 20px">
                          <component :is="option.value" />
                        </el-icon>
                        <span style="margin-top: 8px">
                          {{ option.label }}
                        </span>
                      </span>
                    </li>
                  </ul>
                </el-tab-pane>
                <el-tab-pane v-for="(iconItem, iconIndex) in item.iconOptions" :key="iconIndex" :label="iconItem.label"
                  name="custorm">
                  <ul class="icon-list">
                    <li v-for="(option, index) in iconItem.data" :key="index" class="icon-item"
                      @click="selectIcon(item, option)">
                      <span class="svg-icon">
                        <el-icon style="font-size: 20px">
                          <quick-svg-icon :icon-class="option.value"></quick-svg-icon>
                        </el-icon>
                        <span style="margin-top: 8px">
                          {{ option.label }}
                        </span>
                      </span>
                    </li>
                  </ul>
                </el-tab-pane>
              </el-tabs>
            </el-popover>
          </template>
          <template v-else-if="item.type === 'button'">
            <el-button @click="item.click(item.value)">{{
              item.btnText
              }}</el-button>
          </template>
          <template v-else>
            <el-input v-model="model[item.vModel]" :autocomplete="item.autocomplete" :placeholder="item.placeholder"
              :clearable="item.clearable" :style="{ width: inline ? '400px' : '100%' }" :readonly="(type === 'add' && item.addReadonly) ||
                (type === 'edit' && item.editReadonly) ||
                type === 'detail'
                " />
          </template>
        </el-form-item>
      </div>
    </template>

    <template v-if="!hiddenAction">
      <el-form-item>
        <template v-if="actionSlot">
          <slot name="action" :form-ref="formRef"></slot>
        </template>
        <template v-else>
          <el-button type="primary" @click="handleSubmit">提交</el-button>
          <el-button @click="handleClear">清空</el-button>
        </template>
      </el-form-item>
    </template>
  </el-form>
</template>
<style lang="scss">
.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}

.icon-list {
  overflow-y: scroll;
  list-style: none;
  padding: 0 !important;
  border-top: 1px solid var(--el-border-color);
  border-left: 1px solid var(--el-border-color);
  border-radius: 4px;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  height: 300px;

  .icon-item {
    text-align: center;
    color: var(--el-text-color-regular);
    height: 90px;
    font-size: 13px;
    border-right: 1px solid var(--el-border-color);
    border-bottom: 1px solid var(--el-border-color);
    transition: background-color var(--el-transition-duration);
  }

  .svg-icon {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    height: 100%;
    cursor: pointer;
  }
}
</style>
<style>
.form-design-item {
  margin: 10px;
  padding: 10px;
}

.active {
  border: 3px solid #409eff;
}
</style>
